<?php
/**
 * Created by PhpStorm.
 * User: dumbledore
 * Date: 2017/12/19
 * Time: 下午4:10
 */

defined('BASEPATH') OR exit('No direct script access allowed');
require APPPATH.'/libraries/pay/WxPay.Api.php';
require APPPATH.'/libraries/pay/PayNotifyCallBack.php';

class Wxpay extends CI_Controller {

    public function __construct(){
        parent::__construct();
        $this->load->database();
        $this->load->model('user_model');
        $this->load->model('courier_model');
        $this->load->model('order_model');
        $this->load->library('form_validation');//加载表单验证类库
        $this->load->helper('json');
        $this->load->helper('common');
        $this->output->set_content_type('application/html;charset=utf-8');
    }

    // 订单支付
    public function index() {
        $post = $this->input->post();
        $open_id = '';
        $order_bn = '';
        $fee = '';
        if($post['open_id'] && $post['order_id'])
        {
            $order_info = $this->order_model->query_order_info($post['order_id']);
            if(!$order_info){
                send_json(array('code'=>-1,'data'=>'','msg'=>"没有此订单"));
            }
            if(!$order_info['fee'] || $order_info['fee'] == 0)
            {
                send_json(array('code'=>-1,'data'=>'','msg'=>"请先计算订单价格"));
            }
            $order_bn = $order_info['order_bn'];
            $open_id = $post['open_id'];
            $fee = $order_info['fee'] * 100;
        }else{
            send_json(array('code'=>-1,'data'=>'','msg'=>"缺少参数"));
        }
        //         初始化值对象
        $input = new WxPayUnifiedOrder();
        //         文档提及的参数规范：商家名称-销售商品类目
        $input->SetBody("boxapi");
        //         订单号应该是由小程序端传给服务端的，在用户下单时即生成，demo中取值是一个生成的时间戳
        $input->SetOut_trade_no($order_bn);
        //         费用应该是由小程序端传给服务端的，在用户下单时告知服务端应付金额，demo中取值是1，即1分钱
        $input->SetTotal_fee($fee);
        $input->SetNotify_url("https://boxapi.supergk.com/server/wxpay/notify");//需要自己写的notify.php
        $input->SetTrade_type("JSAPI");
        //         由小程序端传给后端或者后端自己获取，写自己获取到的，
        $input->SetOpenid($open_id);
//        $input->SetOpenid($this->getSession()->openid);
        //         向微信统一下单，并返回order，它是一个array数组
        $order = WxPayApi::unifiedOrder($input);
        //         json化返回给小程序端
        header("Content-Type: application/json");
        return $this->getJsApiParameters($order);
    }

    // 押金支付
    public function deposit_pay() {
        $post = $this->input->post();
        $fee = $this->config->item("deposit_money") * 100;
        if(isset($post['open_id']) && $post['open_id'])
        {
            // 查看是否已经支付成功
            $open_id = $post['open_id'];
            $user_info = $this->user_model->query_wechat_info_by_open_id($open_id);
            if($user_info['deposit'] == 1)
            {
                send_json(array('code'=>-1,'data'=>'','msg'=>"已经支付过押金"));
            }
            // 直接生成订单
            $order_bn = trade_no();
            $this->db->where(array("id"=>$user_info['id']))->update('app_user',array('deposit_bn'=>$order_bn));
            //         初始化值对象
            $input = new WxPayUnifiedOrder();
            //         文档提及的参数规范：商家名称-销售商品类目
            $input->SetBody("boxapi");
            //         订单号应该是由小程序端传给服务端的，在用户下单时即生成，demo中取值是一个生成的时间戳
            $input->SetOut_trade_no($order_bn);
            //         费用应该是由小程序端传给服务端的，在用户下单时告知服务端应付金额，demo中取值是1，即1分钱
            $input->SetTotal_fee($fee);
            $input->SetNotify_url("https://boxapi.supergk.com/server/wxpay/notify");//需要自己写的notify.php
            $input->SetTrade_type("JSAPI");
            //         由小程序端传给后端或者后端自己获取，写自己获取到的，
            $input->SetOpenid($open_id);
//        $input->SetOpenid($this->getSession()->openid);
            //         向微信统一下单，并返回order，它是一个array数组
            $order = WxPayApi::unifiedOrder($input);
            //         json化返回给小程序端
            header("Content-Type: application/json");
            return $this->getJsApiParameters($order);
        }else{
            send_json(array('code'=>-1,'data'=>'','msg'=>"缺少参数"));
        }

    }

    private function getJsApiParameters($UnifiedOrderResult)
    {    //判断是否统一下单返回了prepay_id
        if(!array_key_exists("appid", $UnifiedOrderResult)
            || !array_key_exists("prepay_id", $UnifiedOrderResult)
            || $UnifiedOrderResult['prepay_id'] == "")
        {
            send_json(array('code'=>-1,'data'=>$UnifiedOrderResult,'msg'=>"fail"));
            throw new WxPayException("参数错误");
        }
        $jsapi = new WxPayJsApiPay();
        $jsapi->SetAppid($UnifiedOrderResult["appid"]);
        $timeStamp = time();
        $jsapi->SetTimeStamp("$timeStamp");
        $jsapi->SetNonceStr(WxPayApi::getNonceStr());
        $jsapi->SetPackage("prepay_id=" . $UnifiedOrderResult['prepay_id']);
        $jsapi->SetSignType("MD5");
        $jsapi->SetPaySign($jsapi->MakeSign());
        $parameters = $jsapi->GetValues();
        send_json(array('code'=>0,'data'=>array('data'=>$parameters),'msg'=>"success"));
    }
    //这里是服务器端获取openid的函数
    private function getSession() {
        $code = $this->input->post('code');
        $url = 'https://api.weixin.qq.com/sns/jscode2session?appid='.WxPayConfig::APPID.'&secret='.WxPayConfig::APPSECRET.'&js_code='.$code.'&grant_type=authorization_code';
        $response = json_decode(file_get_contents($url));
        return $response;
    }


    // 回调函数
    public function notify(){
        $notify = new PayNotifyCallBack();
        $notify->Handle(false);

        $now = date("Y-m-d H:i:s");
        $returnValues = $notify->GetValues();
        log_message('error',$now.'发生回调:'.json_encode($returnValues));
        //交易成功
        if(!empty($returnValues['return_code']) && $returnValues['return_code'] == 'SUCCESS'){
            // 解析xml
            libxml_disable_entity_loader(true);
            $postStr = $this->postdata();//接收post数据
            $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
            $arr = $this->object2array($postObj);//对象转成数组
            log_message('error',$now.' 支付完成，返回值:'.json_encode($arr));

            //商户逻辑处理，如订单状态更新为已支付
            $order_bn = $arr['out_trade_no'];
            $transaction_id = $arr['transaction_id'];
            // 判断流水号来源
            $query = $this->db->query("select * from app_order WHERE order_bn = '".$order_bn."'");
            $info1 =  $query->row_array();
            if($info1)
            {
                $this->db->where(array("order_bn"=>$order_bn))->update('app_order',array('is_paid'=>1,'transaction_id'=>$transaction_id));
                // 插入app_account
                $data_arr['user_id'] = $info1['user_id'];
                $data_arr['money'] = $info1['fee'];
                $data_arr['source'] = 3;
                $data_arr['order_id'] = $info1['id'];
                $data_arr['created_at'] = date("Y-m-d H:i:s");
                $this->db->insert("app_account",$data_arr);
            }
            $query2 = $this->db->query("select * from app_user WHERE deposit_bn = '".$order_bn."'");
            $info2 =  $query2->row_array();
            if($info2)
            {
                // 如果是特殊的押金订单，修改user中的deposit
                $this->db->where(array("deposit_bn"=>$order_bn))->update('app_user',array('deposit'=>1,'serial_number'=>$transaction_id));
                // 插入app_account
                $data_arr['user_id'] = $info2['id'];
                $data_arr['money'] = 200;
                $data_arr['source'] = 1;
                $data_arr['created_at'] = date("Y-m-d H:i:s");
                $this->db->insert("app_account",$data_arr);
            }

        }

        echo $notify->ToXml();//返回给微信确认
//        $res = $notify->Queryorder('');
//        send_json(array('code'=>0,'data'=>$res,'msg'=>"test"));
    }


    // 接收post数据
    /*
    *  微信是用$GLOBALS['HTTP_RAW_POST_DATA'];这个函数接收post数据的
    */
    function postdata(){
        $receipt = $_REQUEST;
        if($receipt==null){
            $receipt = file_get_contents("php://input");
            if($receipt == null){
                $receipt = $GLOBALS['HTTP_RAW_POST_DATA'];
            }
        }
        return $receipt;
    }

    //把对象转成数组
    function object2array($array) {
        if(is_object($array)) {
            $array = (array)$array;
        } if(is_array($array)) {
            foreach($array as $key=>$value) {
                $array[$key] = $this->object2array($value);
            }
        }
        return $array;
    }


}
